#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <iterator>
#include <fstream>
#include <array>
#include <algorithm>

#define NO_U128_CMP 1
#define TAB "\t"

typedef struct mime_storage_s
{
    char *ext;
    char *mime_type;
} mime_t;

int ext_count = 0;
mime_t *storage;

int run(char*);
void printList();

int main(int argc,char **argv)
{
    argv++;
    if(argc != 2)
        return 1; // printHelp();

    std::ifstream ifs(*argv, std::ios::binary);
    if (!ifs)
        throw "Error opening file ";
    std::vector<char> file_data = std::vector<char>(std::istreambuf_iterator<char>(ifs), {});
    ifs.close();

    return run(file_data.data());
}

int run(char *mime_data)
{
    char *p1, *p2, *p3;
    mime_t *m_ptr;

    // 统计有多少个后缀
    p1 = mime_data;
    while(p1)
    {
        while(*p1 && *p1 != ' ')
            if(*p1++ == '.')
                ext_count++;
        // 跳过空格
        p1++;
        // 换到下一行
        p1 = strchr(p1, '\n');
        if(p1) p1++;
    }
    // std::cout << "count: " << ext_count << std::endl;
    if(!ext_count)
        return -1;

    std::vector<mime_t> mime_array(ext_count);
    mime_array.shrink_to_fit();
    m_ptr = storage = mime_array.data();

    p1 = mime_data;
    for(int i = 0; i < ext_count; p1 = p3)
    {
        // 为下次循环做准备
        p2 = strchr(p1, '\n');
        if(p2)
        {
            p3 = p2 + 1;
            *p2 = 0;
        }

        // 获取MIME类型，若格式错误则直接返回
        p2 = strchr(p1, ' ');
        if(p2)
            *p2++ = 0;
        else
            return 1;

        // 开始处理后缀类型
        while(*p1)
        {
            if(*p1 == '.')
            {
                *p1++ = 0;
                m_ptr->ext = p1;
                m_ptr->mime_type = p2;
                m_ptr++;
                i++;
            }
            else
                p1++;
        }
    }

    // 进行排序
    std::sort(mime_array.begin(), mime_array.end(), 
        [](const mime_t &mime1, const mime_t &mime2)
        {
#if NO_U128_CMP
            return strcmp(mime1.ext, mime2.ext) < 0;
#else
            char *ext[2] = { mime1.ext, mime2.ext };
            char u128_d[2][sizeof(__uint128_t)] = { };
            __uint128_t *u = (__uint128_t*)u128_d;
            for(int i = 0; i < 2; i++)
            {
                for(int j = 0; j < sizeof(__uint128_t); j++)
                {
                    if(!ext[i][j])
                        break;
                    u128_d[i][j] = ext[i][j];
                }
            }
            return u[0] < u[1];
#endif
        }
    );

    printList();

    return 0;
}

void printList()
{
    for(int i = ext_count; i; i--)
    {
        printf(TAB"{\"%s\", %zu, \"%s\"}%s",
                storage->ext,
                strlen(storage->ext),
                storage->mime_type,
                &",\n"[(i == 1)]
        );
        storage++;
    }
    return;
}
